import pandas as pd
import numpy as np

def check_time_series_anomalies(data, time_col=None, consider_zero_as_anomaly=True):
    """
    检测时间序列数据中的异常值（包括缺失值和零值），包括具体异常的期数
    
    参数:
    data: pandas Series 或 DataFrame
    time_col: 如果是DataFrame，指定时间列的名称
    consider_zero_as_anomaly: 是否将0视为异常值，默认为True
    
    返回:
    dict: 包含异常值统计信息及具体异常位置的字典
    """
    
    result = {}
    
    # 定义异常值检测函数
    def is_anomaly(value):
        if pd.isnull(value):
            return True
        if consider_zero_as_anomaly and value == 0:
            return True
        return False
    
    if isinstance(data, pd.Series):
        # 检查Series中的异常值
        total_values = len(data)
        anomaly_mask = data.apply(is_anomaly)
        anomaly_count = anomaly_mask.sum()
        anomaly_percentage = (anomaly_count / total_values) * 100
        
        result['total_values'] = total_values
        result['anomaly_count'] = anomaly_count  # 包括缺失值和零值
        result['anomaly_percentage'] = round(anomaly_percentage, 2)
        result['has_anomaly'] = anomaly_count > 0
        
        # 分别统计缺失值和零值
        missing_count = data.isnull().sum()
        zero_count = (data == 0).sum() if consider_zero_as_anomaly else 0
        result['missing_count'] = missing_count
        result['zero_count'] = zero_count
        
        # 记录具体异常的索引（期数）
        if anomaly_count > 0:
            anomaly_indices = data[anomaly_mask].index.tolist()
            result['anomaly_indices'] = anomaly_indices  # 所有异常值的索引
            
            # 分别记录缺失值和零值的索引
            result['missing_indices'] = data[data.isnull()].index.tolist()
            if consider_zero_as_anomaly:
                result['zero_indices'] = data[data == 0].index.tolist()
            
            # 检查连续异常的模式
            anomaly_groups = anomaly_mask.ne(anomaly_mask.shift()).cumsum()[anomaly_mask]
            anomaly_patterns = anomaly_groups.value_counts().value_counts()
            result['anomaly_patterns'] = anomaly_patterns.to_dict()
        
    elif isinstance(data, pd.DataFrame):
        if time_col and time_col in data.columns:
            # 确保时间列是datetime类型并按时间排序
            data = data.copy()
            data[time_col] = pd.to_datetime(data[time_col])
            data = data.sort_values(time_col)
            
            # 检查时间间隔是否连续
            time_diffs = data[time_col].diff().dropna()
            expected_interval = time_diffs.mode()[0] if len(time_diffs) > 0 else None
            
            if expected_interval:
                # 检测缺失的时间点
                full_range = pd.date_range(
                    start=data[time_col].min(),
                    end=data[time_col].max(),
                    freq=expected_interval
                )
                missing_times = full_range.difference(data[time_col])
                result['missing_time_points'] = len(missing_times)
                result['missing_times_list'] = missing_times.tolist()
        
        # 检查每列的异常值
        column_stats = {}
        for col in data.columns:
            if col != time_col:  # 跳过时间列
                col_data = data[col]
                total_values = len(col_data)
                
                # 计算异常值总数（缺失值+零值）
                anomaly_mask = col_data.apply(is_anomaly)
                anomaly_count = anomaly_mask.sum()
                anomaly_percentage = (anomaly_count / total_values) * 100
                
                # 分别统计缺失值和零值
                missing_count = col_data.isnull().sum()
                zero_count = (col_data == 0).sum() if consider_zero_as_anomaly else 0
                
                # 记录该列具体异常的索引
                anomaly_indices = col_data[anomaly_mask].index.tolist() if anomaly_count > 0 else []
                missing_indices = col_data[col_data.isnull()].index.tolist() if missing_count > 0 else []
                zero_indices = col_data[col_data == 0].index.tolist() if (consider_zero_as_anomaly and zero_count > 0) else []
                
                column_stats[col] = {
                    'total_values': total_values,
                    'anomaly_count': anomaly_count,  # 异常值总数
                    'anomaly_percentage': round(anomaly_percentage, 2),
                    'missing_count': missing_count,  # 缺失值数量
                    'zero_count': zero_count,        # 零值数量
                    'has_anomaly': anomaly_count > 0,
                    'anomaly_indices': anomaly_indices,  # 所有异常值索引
                    'missing_indices': missing_indices,  # 缺失值索引
                    'zero_indices': zero_indices        # 零值索引
                }
        
        result['columns'] = column_stats
        result['total_columns'] = len(data.columns)
        result['columns_with_anomaly'] = sum(1 for stats in column_stats.values() if stats['has_anomaly'])
    
    return result


def print_anomaly_summary(anomaly_stats):
    """
    打印异常值统计信息的摘要，包括具体异常的期数（缺失值和零值）
    """
    print("=" * 50)
    print("时间序列异常值检测报告（包括缺失值和零值）")
    print("=" * 50)
    
    if 'columns' in anomaly_stats:
        # DataFrame的情况
        print(f"总列数: {anomaly_stats['total_columns']}")
        print(f"存在异常值的列数: {anomaly_stats['columns_with_anomaly']}")
        
        if 'missing_time_points' in anomaly_stats:
            print(f"\n缺失的时间点数量: {anomaly_stats['missing_time_points']}")
            if anomaly_stats['missing_time_points'] > 0:
                print("具体缺失的时间点:")
                for time in anomaly_stats['missing_times_list']:
                    print(f"  - {time}")
        
        print("\n各列异常值详情:")
        for col, stats in anomaly_stats['columns'].items():
            status = "有异常" if stats['has_anomaly'] else "无异常"
            print(f"\n{col}: {status} (异常值总数: {stats['anomaly_count']}/{stats['total_values']}, {stats['anomaly_percentage']}%)")
            if stats['has_anomaly']:
                print(f"  其中：缺失值 {stats['missing_count']} 个，零值 {stats['zero_count']} 个")
                print(f"  具体异常的索引（期数）:")
                for idx in stats['anomaly_indices']:
                    print(f"    - {idx}")
    
    else:
        # Series的情况
        print(f"总数据点: {anomaly_stats['total_values']}")
        print(f"异常值总数: {anomaly_stats['anomaly_count']} ({anomaly_stats['anomaly_percentage']}%)")
        print(f"  其中：缺失值 {anomaly_stats['missing_count']} 个，零值 {anomaly_stats['zero_count']} 个")
        
        if anomaly_stats['has_anomaly']:
            print("存在异常值: 是")
            print("具体异常的索引（期数）:")
            for idx in anomaly_stats['anomaly_indices']:
                print(f"  - {idx}")
            if 'anomaly_patterns' in anomaly_stats:
                print("异常模式:", anomaly_stats['anomaly_patterns'])
    
    print("=" * 50)


# 使用示例
if __name__ == "__main__":
    # 示例1: Series数据
    print("示例1: Series数据检测")
    series_data = pd.read_excel(f"data/全社会用电量当月累计值.xlsx", index_col=0)
    anomaly_stats = check_time_series_anomalies(series_data)
    print_anomaly_summary(anomaly_stats)